<!DOCTYPE html>



  


<html class="theme-next muse use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">





  <link rel="alternate" href="/atom.xml" title="renhao" type="application/atom+xml">






<meta name="description" content="本文总结下面试中常被问到的 http 问题。">
<meta property="og:type" content="article">
<meta property="og:title" content="前端面试总结 http 部分">
<meta property="og:url" content="https://huangrenhao.gitee.io/2020/09/24/http-interview/index.html">
<meta property="og:site_name" content="renhao">
<meta property="og:description" content="本文总结下面试中常被问到的 http 问题。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://huangrenhao.gitee.io/2020/09/24/http-interview/http-interview/tcp-3.png">
<meta property="og:image" content="https://huangrenhao.gitee.io/2020/09/24/http-interview/http-interview/tcp-yongsai-1.png">
<meta property="og:image" content="https://huangrenhao.gitee.io/2020/09/24/http-interview/http-interview/tcp-yongsai-2.png">
<meta property="og:updated_time" content="2020-11-10T01:46:30.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="前端面试总结 http 部分">
<meta name="twitter:description" content="本文总结下面试中常被问到的 http 问题。">
<meta name="twitter:image" content="https://huangrenhao.gitee.io/2020/09/24/http-interview/http-interview/tcp-3.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Muse',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://huangrenhao.gitee.io/2020/09/24/http-interview/">





  <title>前端面试总结 http 部分 | renhao</title>
  








<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">
  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">renhao</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://huangrenhao.gitee.io/2020/09/24/http-interview/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="renhao">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="renhao">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">前端面试总结 http 部分</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2020-09-24T09:44:05+08:00">
                2020-09-24
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope="" itemtype="http://schema.org/Thing">
                  <a href="/categories/interview/" itemprop="url" rel="index">
                    <span itemprop="name">interview</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2020/09/24/http-interview/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count valine-comment-count" data-xid="/2020/09/24/http-interview/" itemprop="commentCount"></span>
                </a>
              </span>
            
          

          
          

          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  10.2k
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  36
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>本文总结下面试中常被问到的 http 问题。<a id="more"></a>来源：<a href="https://juejin.im/post/5e015a60e51d45583d426a15" target="_blank" rel="noopener">关于大厂面试中问到的二十几个 HTTP 面试题</a>  | <a href="https://github.com/shfshanyue/Daily-Question/labels/http" target="_blank" rel="noopener">github</a></p>
<h3 id="http-常见状态码"><a href="#http-常见状态码" class="headerlink" title="http 常见状态码"></a>http 常见状态码</h3><h3 id="http-状态码中-301，302，307-的区别"><a href="#http-状态码中-301，302，307-的区别" class="headerlink" title="http 状态码中 301，302，307 的区别"></a>http 状态码中 301，302，307 的区别</h3><p>301，Moved Permanently，永久重定向，和其他临时重定向状态码最大的区别在于对于未来的请求永久重定向会使用新的 url ，而临时重定向仍然使用旧的 url 。</p>
<p>302，Found。303，See Other。307，Temporary Redirect，都是用于临时重定向，原因在于 HTTP/1.0 和HTTP/1.1 应用程序对这些状态码处理方式不同。如果 HTTP/1.0 服务器收到来自 HTTP/1.0 客户端的 POST 请求之后发送了 302 状态码，服务器就期望客户端能够接收重定向 URL ，并向重定向的 URL 发送一个 GET 请求（POST 请求非幂等）。HTTP/1.1 规范中使用 303 状态码来实现同样的行为（服务器发送 303 状态码来重定向客户端的 POST 请求，在它后面跟上一个 GET 请求），HTTP/1.1 规范又指出对于 HTTP/1.1 客户端用 307 状态码取代 302 状态码来进行临时重定向，即 307 状态码不能自动实现 GET 重定向，仍使用原来的方法。</p>
<blockquote>
<p>参考：<a href="https://www.jianshu.com/p/10c7258b8f52" target="_blank" rel="noopener">简书：网络端口重定向的区别（301，302，303，307）</a></p>
</blockquote>
<h3 id="http-状态码中-502-和-504-的区别"><a href="#http-状态码中-502-和-504-的区别" class="headerlink" title="http 状态码中 502 和 504 的区别"></a>http 状态码中 502 和 504 的区别</h3><ul>
<li><p>502：作为网关或者代理工作的服务器尝试执行请求时，从上游服务器接收到无效的响应。</p>
</li>
<li><p>504：作为网关或者代理工作的服务器尝试执行请求时，未能及时从上游服务器（URI 标识出的服务器，如 HTTP 、FTP 、LDAP ）或者辅助服务器（例如 DNS ）收到响应（某些代理服务器在 DNS 查询超时时会返回 400 或者 500 错误）。</p>
</li>
</ul>
<p>以 nginx 作为代理服务器为例，将请求转发到其他服务器或者 php-cgi 来处理，当 nginx 收到无法理解的响应时就返回 502 。当 nginx 超过自己配置的超时时间还没有收到请求时，就返回 504。这里无法理解的响应指的是 nginx 无法与 php-fpm 进行连接或者在连接 php-fpm 一段时间后连接断开。php-fpm 指的是 FastCGI 进程管理器，用于支持平滑停止、启动高级进程管理功能，监听不同端口和使用不同 php.ini 配置文件等。</p>
<blockquote>
<p>参考：</p>
<ul>
<li><a href="https://juejin.im/post/5b54635ae51d451951133d85" target="_blank" rel="noopener">掘金：nginx 502 和 504 超时演示</a></li>
<li><a href="https://github.com/zhangyachen/zhangyachen.github.io/issues/89" target="_blank" rel="noopener">github：502 VS 504</a></li>
<li><a href="https://www.php.cn/manual/view/4.html" target="_blank" rel="noopener">php 中文手册</a></li>
</ul>
</blockquote>
<h3 id="简述-http-的缓存机制"><a href="#简述-http-的缓存机制" class="headerlink" title="简述 http 的缓存机制"></a>简述 http 的缓存机制</h3><h4 id="强缓存"><a href="#强缓存" class="headerlink" title="强缓存"></a>强缓存</h4><p>配置在 Cache-Control 字段内</p>
<ul>
<li>max-age：相对时间，最大合法生存时间</li>
</ul>
<p>Expire 字段：绝对时间</p>
<h4 id="协商缓存"><a href="#协商缓存" class="headerlink" title="协商缓存"></a>协商缓存</h4><ul>
<li>Last-modify/If-Modify-Since：浏览器第一次请求一个资源返回的响应头中会包含 Last-Modify，之后的请求中请求头都会包含 If-Modify-Since。如果命中缓存则返回 304 且返回的响应头中无 Last-Modify</li>
<li>ETag/If-None-Match：与 Last-Modify 不一样的是返回 304 Not Modified 的响应时，由于 Etag 重新生成，所有返回的响应中响应头包含 Etag，即使没有发生变化</li>
</ul>
<p>Last-Modify 和 Etag 可以一起使用，Etag 优先级更高，即先验证 Etag，一致情况下才会验证 Last-Modify</p>
<p>Cache-Control 字段的各种值：</p>
<ul>
<li>可缓存性：<ul>
<li>public：响应可以被任何对象（发送请求的客户端、代理服务器）缓存</li>
<li>private：响应只能被单个用户缓存，不能作为共享缓存（代理服务器不能缓存）</li>
<li>no-cache、no-store</li>
</ul>
</li>
<li>到期：<ul>
<li><code>max-age=&lt;seconds&gt;</code></li>
<li><code>max-stale[=&lt;seconds&gt;]</code>，表明客户端愿意接受一个已经过期的资源，给出的秒数表示响应不能超过该给定的时间</li>
<li><code>min-fresh=&lt;seconds&gt;</code>，表示客户端希望获取一个能在指定秒数内保持其最新状态的响应</li>
<li><code>stale-while-revalidate=&lt;seconds&gt;</code>，表示客户端愿意接受陈旧的响应，同时在后台异步检查新的响应，秒值指示客户愿意接受陈旧响应的时间长度</li>
<li><code>stale-if-error=&lt;seconds&gt;</code>，表示如果新的检查失败，则客户愿意接受陈旧的响应，秒数表示客户在初始到期后愿意接受陈旧响应的时间</li>
</ul>
</li>
<li>重新验证和重新加载<ul>
<li>must-revalidate，资源过期后在成功向服务器验证之前不能用该资源响应</li>
<li>immutable，响应正文不会随时间而改变，资源在服务器上不发生改变，客户端也不应发送重新验证请求头</li>
</ul>
</li>
</ul>
<h3 id="http-proxy-的原理是什么"><a href="#http-proxy-的原理是什么" class="headerlink" title="http proxy 的原理是什么"></a>http proxy 的原理是什么</h3><p>可以从代理的功能、代理的示例、代理的部署位置、代理获取流量的方式、有无代理的 URI 的解析方式进行阐述。参见 HTTP 权威指南总结代理部分。</p>
<p>nginx 反向代理设置：<code>proxy_pass</code></p>
<h3 id="随着-http2-的发展，前端性能优化中的哪些传统方案可以被替代"><a href="#随着-http2-的发展，前端性能优化中的哪些传统方案可以被替代" class="headerlink" title="随着 http2 的发展，前端性能优化中的哪些传统方案可以被替代"></a>随着 http2 的发展，前端性能优化中的哪些传统方案可以被替代</h3><p>雪碧图、内联（将图片转化为 base64 编码嵌入 url 中）</p>
<h3 id="前端中的一些优化方法-前端性能优化"><a href="#前端中的一些优化方法-前端性能优化" class="headerlink" title="前端中的一些优化方法/前端性能优化"></a>前端中的一些优化方法/前端性能优化</h3><ul>
<li><p>优化渲染</p>
<ul>
<li>css 放到 head：css 有单独的下载线程异步下载，css 的加载不会影响 dom 树解析，但会阻塞 render 树渲染。</li>
<li>script 放到 底部或者加上 defer 或 async：浏览器渲染进程中 GUI 渲染线程与 js 引擎线程互斥，故当 HTML 解析到 script 标签时会暂停构建 dom，完成 js 下载并解析之后才会从暂停的地方重新开始。加了 defer 之后脚本文件下载与 html 解析并行执行，不过需要等待 html 解析完成之后再顺序执行。加了 async 之后脚本文件下载与 html 解析也是并行执行，但脚本下载完成之后暂停解析 html ，立即执行 js，async 不能确保执行的顺序。</li>
<li>预加载：尽早获取资源，不阻塞 onload。使用 <code>&lt;link rel=&#39;preload&#39;...</code></li>
<li>预渲染：下载后的文件预先在后台渲染，使用 <code>&lt;link rel=&#39;prerender&#39; ...</code></li>
<li>懒执行：将某些逻辑延迟到使用时再计算</li>
<li>懒加载：不关键资源延后加载，只加载自定义区域  </li>
</ul>
</li>
<li><p>减少请求数量（tcp 三次握手延时）</p>
<ul>
<li><p>小图片使用 base64 编码嵌入 css 中的 url 中</p>
</li>
<li><p>使用雪碧图</p>
</li>
<li><p>使用缓存：强缓存与协商缓存区别</p>
</li>
<li><p>使用持久连接：HTTP/1.0+“keep-alive”连接和 HTTP/1.1“persistent”连接，只有当连接上所有的报文都有正确的、自定义报文长度时（实体部分长度和 content-length 一致）连接才  能保持持久。</p>
<p>HTTP/1.0 keep-alive 连接的客户端可以通过包含 Connection:Keep-Alive 首部请求将连接保持在打开状态，如果服务器愿意为下一条请求将连接保持在打开状态就在响应中包含相同的首部，如果响应中没有 Connection:Keep-Alive 首部客户端就认为服务器不支持keep-alive并在发回响应报文之后关闭连接。</p>
<p>HTTP/1.1 持久连接在默认情况下是激活的</p>
</li>
<li><p>使用 http2</p>
</li>
</ul>
</li>
<li><p>减少请求时间</p>
<ul>
<li>dns 预解析、预读取：使浏览器主动进行域名解析，范围包括文档中的所有链接。使用<code>&lt;link rel=&#39;dns-prefetch&#39;...</code></li>
<li>静态资源使用 cdn，可以使用多个 cdn 域名（单个域名有链接限制），cdn 域名要和主站域名不同（否则会带 cookie ）</li>
</ul>
</li>
</ul>
<h3 id="HTTP-1-0-、-HTTP-2-0、-HTTP-3-0"><a href="#HTTP-1-0-、-HTTP-2-0、-HTTP-3-0" class="headerlink" title="HTTP 1.0 、 HTTP 2.0、 HTTP 3.0"></a>HTTP 1.0 、 HTTP 2.0、 HTTP 3.0</h3><p>详情参考 <a href="https://huangrenhao.gitee.io/2020/09/24/http-next/">http 2 与 http 3</a></p>
<h3 id="websocket-、socket、-http"><a href="#websocket-、socket、-http" class="headerlink" title="websocket 、socket、 http"></a>websocket 、socket、 http</h3><p>websocket 是 HTML5 中提出的一种协议，在 osi 模型中与 http 同属于应用层协议，基于 tcp 协议。对于 websocket 必须依赖 http 协议进行一次握手，握手成功后数据直接从 tcp 通道传输，与 http 无关。传统web中实现实时通信通用方式是使用 http 进行轮询或长轮询（客户端发送请求后服务端如果没有数据就保持连接直到有数据或者连接超时），浪费带宽又占用服务器内存，websocket 可以极大的减少不必要的网络流量与延迟。</p>
<p>socket 并不是一个协议，工作在 osi 模型会话层，是为了方便使用底层协议，（tcp、udp）而存在的一个抽象层。</p>
<blockquote>
<p>websocket 连接过程:</p>
<p>首先，客户端发起http请求，经过3次握手后，建立起TCP连接；http请求里存放WebSocket支持的版本号等信息，如：Upgrade、Connection、WebSocket-Version等；<br>然后，服务器收到客户端的握手请求后，同样采用HTTP协议回馈数据；<br>最后，客户端收到连接成功的消息后，开始借助于TCP传输信道进行全双工通信。</p>
</blockquote>
<p>websocket 和 ajax 不同的是 websocket 是支持跨域的。</p>
<h3 id="get-post-请求区别"><a href="#get-post-请求区别" class="headerlink" title="get post 请求区别"></a>get post 请求区别</h3><p>GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。你要给GET加上request body，给POST带上url参数，技术上是完全行的通的。 </p>
<p>由于HTTP的规定和浏览器/服务器的限制，导致他们在应用过程中体现出一些不同。（ url、request body）</p>
<p><strong>重大区别</strong>：GET产生一个TCP数据包；POST产生两个TCP数据包。对于GET方式的请求，浏览器会把http header和data一并发送出去，服务器响应200（返回数据）；而对于POST，浏览器先发送header，服务器响应100 continue，浏览器再发送data，服务器响应200 ok（返回数据）。</p>
<blockquote>
<p>注意：</p>
<ul>
<li>据研究，在网络环境好的情况下，发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下，两次包的TCP在验证数据包完整性上，有非常大的优点。</li>
<li>并不是所有浏览器都会在POST中发送两次包，Firefox就只发送一次</li>
<li>发两次包可以让服务器查看用户是否有权限、文件名是否符合规范等，就不再处理请求体的数据（直接丢弃）而不用等到整个请求都处理完之后再拒绝。</li>
</ul>
</blockquote>
<h3 id="为什么-tcp-建立连接需要三次握手，而不是两次"><a href="#为什么-tcp-建立连接需要三次握手，而不是两次" class="headerlink" title="为什么 tcp 建立连接需要三次握手，而不是两次?"></a>为什么 tcp 建立连接需要三次握手，而不是两次?</h3><p>谢希仁版《计算机网络》中的例子是这样的，“已失效的连接请求报文段”的产生在这样一种情况下：client发出的第一个连接请求报文段并没有丢失，而是在某个网络结点长时间的滞留了，以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后，就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段，同意建立连接。假设不采用“三次握手”，那么只要server发出确认，新的连接就建立了。由于现在client并没有发出建立连接的请求，因此不会理睬server的确认，也不会向server发送ack包。（校注：此时因为client没有发起建立连接请求，所以client处于CLOSED状态，接受到任何包都会丢弃，谢希仁举的例子就是这种场景。但是如果服务器发送对这个延误的旧连接报文的确认的同时，客户端调用connect函数发起了连接，就会使客户端进入SYN_SEND状态，当服务器那个对延误旧连接报文的确认传到客户端时，因为客户端已经处于SYN_SEND状态，所以就会使客户端进入ESTABLISHED状态，此时服务器端反而丢弃了这个重复的通过connect函数发送的SYN包，见第三个图。而连接建立之后，发送包由于SEQ是以被丢弃的SYN包的序号为准，而服务器接收序号是以那个延误旧连接SYN报文序号为准，导致服务器丢弃后续发送的数据包）但server却以为新的运输连接已经建立，并一直等待client发来数据。这样，server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况，client不会向server的确认发出确认。server由于收不到确认，就知道client并没有要求建立连接。</p>
<p><img src="./http-interview/tcp-3.png" alt="image-20200418101821592"></p>
<p>tcp 三次握手中的第三次客户端发送 ACK 给服务端，如何判断这个 ACK 被客户端接收了？答：当客户端收到服务端发送的 SYN+ACK 后，其状态变为 established， 并发送 ACK 给服务端，如果这个 ACK 在网络中丢失，服务端的状态一直维持 SYN_RECV ，并依次等待 3s,6s,12s 后重新发送 SYN+ACK，如果重发指定次数后客户端没有收到应答，服务端就会关闭这个连接。客户端会认为连接已经创建成功，会尝试发送数据，但服务端会以<strong>RST</strong>包响应（RST包用于强制关闭 tcp 连接），客户端就能收到服务端出错。</p>
<h3 id="tcp-四次挥手为什么需要四次-能不能变成三次挥手"><a href="#tcp-四次挥手为什么需要四次-能不能变成三次挥手" class="headerlink" title="tcp 四次挥手为什么需要四次? 能不能变成三次挥手?"></a>tcp 四次挥手为什么需要四次? 能不能变成三次挥手?</h3><p>TCP是全双工通信，Client 在自己已经不会在有新的数据要发送给 Server 后，可以发送 FIN 信号告知 Server，这边已经终止 Client 到对端 Server 那边的数据传输。但是，这个时候对端 Server 可以继续往 Client 这边发送数据包。于是，两端数据传输的终止在时序上是独立并且可能会相隔比较长的时间，这个时候就必须最少需要2+2 = 4 次挥手来完全终止这个连接。但是，如果Server在收到Client的FIN包后，在也没数据需要发送给Client了，那么对Client的ACK包和Server自己的FIN包就可以合并成为一个包发送过去，这样四次挥手就可以变成三次了。</p>
<h3 id="tcp-四此挥手后为什么还需要等待-2msl"><a href="#tcp-四此挥手后为什么还需要等待-2msl" class="headerlink" title="tcp 四此挥手后为什么还需要等待 2msl"></a>tcp 四此挥手后为什么还需要等待 2msl</h3><p>在Client发送出最后的ACK回复，但该ACK可能丢失。Server如果没有收到ACK，将不断重复发送FIN片段。所以Client不能立即关闭，它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器，等待2MSL的时间。如果在该时间内再次收到FIN，那么Client会重发ACK并再次等待2MSL。</p>
<blockquote>
<p>所谓的2MSL是两倍的MSL(Maximum Segment Lifetime最大 报文段存活时间（往返时间）)。MSL指一个片段在网络中最大的存活时间，2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL，Client都没有再次收到FIN，那么Client推断ACK已经被成功接收，则结束TCP连接。</p>
</blockquote>
<h3 id="大量-TIME-WAIT-产生原因及解决方法"><a href="#大量-TIME-WAIT-产生原因及解决方法" class="headerlink" title="大量 TIME_WAIT 产生原因及解决方法"></a>大量 TIME_WAIT 产生原因及解决方法</h3><p>对于基于 tcp 的 http 协议，关闭 tcp 连接的是 server 端，这样 server 端就进入 TIME_WAIT 状态，对于大访问量的 web server 会存在大量的  TIME_WAIT 。</p>
<p>解决方法：</p>
<ul>
<li>开启 socket 重用，允许将 TIME_WAIT 的 socket 重新用于 TCP 连接</li>
<li>开启快速回收</li>
</ul>
<h3 id="tcp-在-listen-时参数-backlog-的意义"><a href="#tcp-在-listen-时参数-backlog-的意义" class="headerlink" title="tcp 在 listen 时参数 backlog 的意义"></a>tcp 在 listen 时参数 backlog 的意义</h3><p>linux 内核中会维护两个队列：</p>
<ul>
<li>未完成队列：接收到一个 SYN 建立连接请求，处于 SYN-RCVD 状态</li>
<li>已完成队列：已完成 tcp 三次握手过程，处于 ESTABLISHED 状态</li>
</ul>
<p>当有一个SYN到来请求建立连接时，就在未完成队列中新建一项。当三次握手过程完成后，就将套接口从未完成队列移动到已完成队列。backlog曾被定义为两个队列的总和的最大值，也曾将backlog的1.5倍作为未完成队列的最大长度。一般将backlog指定为5</p>
<h3 id="accept-发生在三次握手的哪一步"><a href="#accept-发生在三次握手的哪一步" class="headerlink" title="accept 发生在三次握手的哪一步"></a>accept 发生在三次握手的哪一步</h3><p>accept会监听已完成队列是否非空，当队列为空时，accept就会阻塞。当队列非空时，就从已完成队列中取出一项并返回。而已完成队列中的都是三次握手过程已经完成的，因此accept发生在三次握手之后。</p>
<h3 id="SYN-洪范攻击"><a href="#SYN-洪范攻击" class="headerlink" title="SYN 洪范攻击"></a>SYN 洪范攻击</h3><p>伪装的IP向服务器发送一个SYN请求建立连接，然后服务器向该IP回复SYN和ACK，但是找不到该IP对应的主机，当超时时服务器收不到ACK会重复发送。当大量的攻击者请求建立连接时，服务器就会存在大量未完成三次握手的连接，服务器主机backlog被耗尽而不能响应其它连接。即SYN泛洪攻击 （属于DOS的一种，发送大量的半连接请求，耗费CPU和内存资源，引起网络堵塞甚至系统瘫痪）。当一个主机向服务器发送SYN请求连接，服务器回复ACK和SYN后，攻击者截获ACK和SYN，然后伪装成原始主机继续与服务器进行通信。</p>
<p>防范措施：</p>
<p>　　1、降低SYN timeout时间，使得主机尽快释放半连接的占用<br>　　2、采用SYN cookie设置，如果短时间内连续收到某个IP的重复SYN请求，则认为受到了该IP的攻击，丢弃来自该IP的后续请求报文<br>　　3、在网关处设置过滤，拒绝将一个源IP地址不属于其来源子网的包进行更远的路由</p>
<h3 id="DOS-攻击（拒绝服务攻击）"><a href="#DOS-攻击（拒绝服务攻击）" class="headerlink" title="DOS 攻击（拒绝服务攻击）"></a>DOS 攻击（拒绝服务攻击）</h3><p>DOS攻击利用合理的服务请求占用过多的服务资源，使正常用户的请求无法得到响应。常见的DOS攻击有计算机网络带宽攻击和连通性攻击：</p>
<ul>
<li><p>带宽攻击指以极大的通信量冲击网络，使得所有可用网络资源都被消耗殆尽，最后导致合法的用户请求无法通过。</p>
</li>
<li><p>连通性攻击指用大量的连接请求冲击计算机，使得所有可用的操作系统资源都被消耗殆尽，最终计算机无法再处理合法用户的请求。</p>
</li>
</ul>
<h3 id="死亡值-ping"><a href="#死亡值-ping" class="headerlink" title="死亡值 ping"></a>死亡值 ping</h3><p>”死亡值ping”就是故意产生畸形的测试ping包，声称自己的尺寸超过ICMP上限，也就是加载的尺寸超过64KB上限，使未采取保护措施的网络系统出现内存分配错误，导致TCP/IP协议栈崩溃，最终接收方宕机。</p>
<blockquote>
<p>许多操作系统的TCP/IP协议栈规定<strong>ICMP包大小为64KB</strong>（网间控制报文），且在对包的标题头进行读取之后，要根据该标题头里包含的信息来为有效载荷生成缓冲区。</p>
<p>ping：packet Internet groper，用于测试网络连通器的程序。ping 发送一个 ICMP（Internet control messages protocol），回声请求消息给目的地并报告是否收到所希望的 ICMP echo。ping 工作在tcp/ip 协议栈中的应用层。</p>
<ul>
<li>工作原理：利用网络上机器 IP 地址的唯一性，给目标 IP 地址发送一个数据包，再要求对方返回一个同样大小的数据包来确定两台网络机器是否连接相通，时延多少</li>
</ul>
<p>为了提高 IP 数据报交付成功机会，在网络层使用 ICMP 来控制主机或路由器报告差错和异常情况，ICMP 报文作为 IP 数据报的数据，再加上首部组成 IP 数据报发出去，ICMP 协议是 IP 协议。</p>
</blockquote>
<h3 id="tcp-保活机制"><a href="#tcp-保活机制" class="headerlink" title="tcp 保活机制"></a>tcp 保活机制</h3><p>保活机制由一个定时器实现，是服务器用来确定什么时候应该断开连接的一种机制，保活机制可以被设置在 tcp 连接的一端、两端。如果建立连接后客户端出现故障，若服务器开启保活机制，则会向客户端发送保活探测报文，如果在保活探测时间范围内没有收到响应就继续发送，直到保活探测的次数，对方被确认为不可达后连接中断。</p>
<h3 id="出现-RST-包的原因"><a href="#出现-RST-包的原因" class="headerlink" title="出现 RST 包的原因"></a>出现 RST 包的原因</h3><p>RST 是 tcp 首部中的 6 个标志比特之一，表示重置、复位连接。出现情况有：</p>
<ul>
<li>服务器端口未打开而客户端来连接时</li>
<li>在一个已关闭的 socket 上收到数据</li>
<li>请求超时</li>
<li>提前关闭</li>
</ul>
<h3 id="tcp-和-udp-区别"><a href="#tcp-和-udp-区别" class="headerlink" title="tcp 和 udp 区别"></a>tcp 和 udp 区别</h3><ul>
<li>tcp 是面向连接的，即在数据交互之前必须通过三次握手建立连接，而 udp 是无连接的，没有建立连接过程。</li>
<li>tcp 是可靠传输，通过确认和超时重传机制来保证数据传输的可靠性，而 udp 是不可靠传输，可能丢包。tcp 可以保证数据顺序，而 udp 不保证。tcp 还提供了拥塞控制、滑动窗口等机制来保证传输的质量，而 udp 没有。</li>
<li>tcp 是基于字节流，将数据看作无结构的字节流进行传输，当应用程序交给 tcp 的数据太长时 tcp 就会对数据进行分段，故 tcp 的数据是无边界的。而 udp 是面向数据报的，udp 不会对数据报进行任何的拆分处理，故 udp 保留了应用层数据的边界。</li>
</ul>
<h3 id="tcp-为什么是可靠的"><a href="#tcp-为什么是可靠的" class="headerlink" title="tcp 为什么是可靠的"></a>tcp 为什么是可靠的</h3><ul>
<li>分块发送：应用数据被分割成 tcp 认为最合适发送的数据块，将数据截断为合理长度，udp 中产生的数据报长度保持不变。</li>
<li><strong>定时确认重传</strong>：当TCP发出一个段后，它启动一个定时器，等待目的端确认收到这个报文段。如果不能及时收到一个确认，将重发这个报文段。</li>
<li>确认：当TCP收到发自TCP连接另一端的数据，它将发送一个确认。这个确认不是立即发送，通常将推迟几分之一秒</li>
<li><strong>数据校验</strong>：TCP将保持它首部和数据的检验和。这是一个端到端的检验和，目的是检测数据在传输过程中的任何变化。如果收到端的检验和有差错，TCP将丢弃这个报文段并不确认收到此报文段（希望发端超时并重发）。</li>
<li><strong>正确排序</strong>：由于IP数据报的到达可能会失序，因此TCP报文段的到达也可能会失序。如果必要，TCP将对收到的数据进行重新排序，将收到的数据以正确的顺序交给应用层。</li>
<li><strong>重复丢弃</strong>：IP数据报会发生重复，TCP的接收端必须丢弃重复的数据。</li>
<li><strong>流量控制</strong>：TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出（TCP可以进行流量控制，防止较快主机致使较慢主机的缓冲区溢出）。TCP使用的流量控制协议是可变大小的滑动窗口协议。</li>
</ul>
<h3 id="tcp-的滑动窗口和流量控制"><a href="#tcp-的滑动窗口和流量控制" class="headerlink" title="tcp 的滑动窗口和流量控制"></a>tcp 的滑动窗口和流量控制</h3><h4 id="滑动窗口"><a href="#滑动窗口" class="headerlink" title="滑动窗口"></a>滑动窗口</h4><p>为了提高速度，TCP并没有按照字节单个发送而是将数据流划分为片段。片段内所有字节都是一起发送和接收的，因此也是一起确认的。确认机制没有采用message ID字段，而是使用的片段内最后一个字节的sequence number。因此一次可以处理不同的字节数，这一数量即为片段内的sequence number。</p>
<p>假设A和B之间新建立了一条TCP连接。设备A需要传送一长串数据流，但设备B无法一次全部接收，所以它限制设备A每次发送分段指定数量的字节数，直到分段中已发送的字节数得到确认。之后，设备A可以继续发送更多字节。每一个设备都对发送，接收及确认数据进行追踪。如果我们在任一时间点对于这一过程做一个“快照”，那么我们可以将TCP buffer中的数据分为以下四类，并把它们看作一个时间轴： <strong>已发送已确认、【已发送但尚未确认、未发送而接收方已Ready】、未发送而接收方Not Ready</strong>。接收方采用类似机制：<strong>【已接收并已确认，尚未接受但准备好接收】，以及尚未接收并尚未准备好接收的数据</strong>。每一次确认接收以后，这一过程都会发生，从而让窗口滑动过整个数据流以供传输。</p>
<h4 id="流量控制"><a href="#流量控制" class="headerlink" title="流量控制"></a>流量控制</h4><p>接收方传递信息给发送方，使其不要发送数据太快，是一种端到端的控制。主要的方式就是返回的ACK中会包含自己的接收窗口的大小，并且利用大小来控制发送方的数据发送。</p>
<p>如果B已经告诉A自己的缓冲区已满，于是A停止发送数据；等待一段时间后，B的缓冲区出现了富余，于是给A发送报文告诉A我的rwnd大小为400，但是这个报文不幸丢失了，于是就出现A等待B的通知||B等待A发送数据的死锁状态。为了处理这种问题，TCP引入了持续计时器（Persistence timer），当A收到对方的零窗口通知时，就启用该计时器，时间到则发送一个1字节的探测报文，对方会在此时回应自身的接收窗口大小，如果结果仍未0，则重设持续计时器，继续等待。</p>
<h3 id="tcp-的拥塞控制"><a href="#tcp-的拥塞控制" class="headerlink" title="tcp 的拥塞控制"></a>tcp 的拥塞控制</h3><ul>
<li><p>产生拥塞的原因：在某段时间，若对网络中某一资源的需求超过了该资源所能提供的可用部分，网络的性能就会变坏。</p>
</li>
<li><p><strong>拥塞控制</strong>与<strong>流量控制</strong>的区别：拥塞控制是防止过多的数据注入网络中，使得网络中路由器或链路不致过载，有一个前提是，网络能够承受现有的网络负荷，是一个<strong>全局性</strong>过程；流量控制是指点对点通信的控制，做的是抑制发送端发送数据的速率，便于接收端来得及接收。即拥塞控制是防止把网络填满，流量控制是为了防止发送方把接收方缓存塞满。</p>
</li>
<li><p>四种算法：</p>
<ul>
<li><p><strong>慢开始和拥塞避免</strong></p>
<p>基于窗口的拥塞控制，在发送方维护一个<strong>拥塞窗口</strong>（cwnd），大小等于发送窗口，通过出现了<strong>超时</strong>来判断网络出现拥塞。慢开始的思路是一开始发送方发送一个字节，在收到接收方的确认，然后发送的字节数量增大一倍（也就是按照<strong>指数</strong>增长的速率），从小到大逐步增大cwnd，直到cwnd 达到<strong>慢开始门限</strong>（ssthresh），停止慢开始算法，使用拥塞避免算法，拥塞避免算法思路是增长速率变为<strong>线性</strong>增长，也就是每经过一个往返时间RTT就把发送方的cwnd加1</p>
<p><img src="./http-interview/tcp-yongsai-1.png" alt="tcp" style="zoom:75%;"></p>
</li>
<li><p><strong>快重传和快恢复</strong></p>
<p>通过上面两个算法可以使得网络传输速率一直增大，直到出现超时，这时候需要将cwnd重新调整到1个字节开始，使用慢开始算法，同时需要将慢开始门限ssthresh调整为cwnd（超时点）的一半，继续执行慢开始、拥塞避免算法。如果收到<strong>3-ACK</strong>（发送方一连接收到3个对同一个报文段的重复确认），这种可能的情况是，并不是发生了拥塞，可能是报文丢失，所以发送方不执行慢开始算法，直接使用快重传算法，立即发送缺失的报文段。同时执行快恢复算法，将门限值（ssthresh）调整为此时cwnd的一半，并执行拥塞避免算法。</p>
<p><img src="./http-interview/tcp-yongsai-2.png" alt="tcp"></p>
</li>
</ul>
</li>
</ul>
<h3 id="tcp-粘包及拆包"><a href="#tcp-粘包及拆包" class="headerlink" title="tcp 粘包及拆包"></a>tcp 粘包及拆包</h3><blockquote>
<p>TCP 是以字节流的方式传输数据，传输的最小单位为一个报文段（segment）。TCP 首部中有个选项 (Options)的字段，常见的选项为 MSS (Maximum Segment Size最大消息长度)，它是收发双方协商通信时每一个报文段所能承载的最大有效数据的长度。数据链路层每次传输的数据有个最大限制MTU (Maximum Transmission Unit)，一般是1500比特，超过这个量要分成多个报文段，MSS 则是这个最大限制减去 TCP 的首部，光是要传输的数据的大小，一般为1460比特。换算成字节，也就是180多字节。</p>
<p>MSS = MTU - Header</p>
<p>TCP 为提高性能，发送端会将需要发送的数据发送到发送缓存，等待缓存满了之后，再将缓存中的数据发送到接收方。同理，接收方也有接收缓存这样的机制，来接收数据。</p>
</blockquote>
<p>粘包发生原因：</p>
<ol>
<li>要发送的数据大于TCP发送缓冲区剩余空间大小，将会发生拆包。</li>
<li>待发送数据大于MSS（最大报文长度），TCP在传输前将进行拆包。</li>
<li>应用程序写入数据小于剩余缓存大小，网卡将应用多次写入的数据先缓存起来，然后一起发送到网络上，这将会发生粘包。</li>
<li>接收数据端的应用层没有及时读取接收缓存中的数据，将发生粘包。</li>
</ol>
<p>粘包解决方案拆包：</p>
<ol>
<li>设置定长消息，服务端每次读取既定长度的内容作为一条完整消息。</li>
<li>设置消息边界，数据结尾尾增加特殊字符分割。</li>
<li>使用带消息头的协议，消息头存储消息开始标识及消息长度信息，接收方获取消息头的时候解析出消息长度，然后向后读取该长度的内容。</li>
</ol>
<blockquote>
<p><a href="https://segmentfault.com/a/1190000022144695#item-1" target="_blank" rel="noopener">参考：tcp 考点总结</a></p>
</blockquote>
<h3 id="有哪些常见的服务端推送的通信解决方案？它们的优劣分别是什么？"><a href="#有哪些常见的服务端推送的通信解决方案？它们的优劣分别是什么？" class="headerlink" title="有哪些常见的服务端推送的通信解决方案？它们的优劣分别是什么？"></a>有哪些常见的服务端推送的通信解决方案？它们的优劣分别是什么？</h3><p>1.基于轮询：<br>优点：开发简单，客户端实现即可，不需要服务端配合<br>缺点：大多数情况下无用请求，占用服务端资源<br>实现方式：客户端每隔一段时间调用接口，无论有没有数据，接口立即返回.<br>使用场景：不想折腾的开发者，消息及时性要求没那么高，服务器资源资源足。<br>2.基于长轮询<br>优点：消息及时，命中率高，消耗服务端资源少<br>缺点：服务端和客户端需要同时改造，消息会有部分延迟（发生在请求交替之时）<br>实现方式：客户端在上次请求返回后，在发送下次请求，服务端当有数据或者超时后返回，没有数据时hang住链接（超时时间需要综合考虑服务器性能和及时性做出平衡，有代理的话需要考虑代理对于链接的超时机制）。<br>使用场景：扫码登录，微信网页端获取消息等。<br>3.长链接<br>优点：通信及时，通信模式采用双工，类似于打电话<br>缺点：服务端和客户端需要同时改造，当链接过多时，消耗服务端资源比较大。<br>实现方式：客户端和服务端建立长链接，基于http1.1 ,keepalive ,websocket,comet，iframe等，基于socket的需要维持心跳<br>使用场景：实时性要求很高，银行系统，股票系统等</p>
<h4 id="content-type"><a href="#content-type" class="headerlink" title="content-type"></a>content-type</h4><p>常见的值：</p>
<ul>
<li><code>application/x-www-form-urlencoded</code>：浏览器的原生 form 表单，form 表单不设置 enctype 字段就是这个，提交的数据按照 <code>key1=value1&amp;key2=value2</code> 进行编码。其他的如手写 ajax 也可使用这种，需要设置相应的header</li>
<li><code>multipart/form-data</code>：常见 POST 数据提交的方式，一般用来上传文件，各大服务端语言支持良好。使用表单 form 上传文件需要设置 form 的 enctype 字段为这个值。如果是手写 ajax 可以调用它 xhr 的 setRequestHeader 设置 Content-Type</li>
<li><code>application/json</code>：消息主体是序列化后的 JSON 字符串，支持复杂的结构化数据，树形结构展示</li>
<li><code>text/xml</code>：xml 面向数据，一般用于存储数据、存储配置文件等需要结构化存储的地方使用</li>
</ul>
<blockquote>
<p>axios 默认 post 请求的 content-type 为 application/x-www-form-urlencoded，可以在 创建 axios 实例时在参数 header 中进行修改</p>
<p>form 表单 enctype 字段的值：application/x-ww-form-urlencoded, multipart/form-data, text/plain （仅空格转换为 ‘+’）</p>
</blockquote>
<h3 id="cdn-原理"><a href="#cdn-原理" class="headerlink" title="cdn 原理"></a>cdn 原理</h3><p>cdn 技术把源站内容缓存到多个节点，用户向源站域名发起请求时，请求会被调度到最接近用户的服务节点。降低用户访问延迟，提升可用性。</p>
<p>主要原理是：给源站域名加上 CNAME，别名为加速节点的域名，当用户向源站发起请求时，dns 服务器解析源站域名时会发现有 CNAME 记录，这时 dns 服务器会向 CNAME 域名发起请求，请求会被调度至加速节点的域名。</p>
<blockquote>
<p><a href="https://www.jianshu.com/p/14dede92b02f" target="_blank" rel="noopener">cdn 实现原理</a></p>
</blockquote>
<h3 id="https-amp-amp-ca"><a href="#https-amp-amp-ca" class="headerlink" title="https &amp;&amp; ca"></a>https &amp;&amp; ca</h3><p>http 明文传输，存在信息窃听、信息篡改、信息劫持</p>
<p>https ，加密传输：身份验证（非对称加密）、信息加密（对称加密）</p>
<p><strong>https 中 ssl 过程</strong>：</p>
<ol>
<li><strong>协商加密算法</strong>：浏览器 A 向服务器发送浏览器的 ssl 版本号和一些可选的加密算法，B从中选择自己所支持的算法，并告知A</li>
<li><strong>服务器鉴别</strong>：服务器 B 向浏览器 A 发送包含其 RSA 公钥的数字证书，A 使用该证书的认证机构 CA 公开发布的 RSA 公钥对该证书进行验证</li>
<li><strong>会话秘钥计算</strong>：由浏览器 A 产生一个随机秘密数，用服务器 B 的 RSA 公钥进行加密后发送给 B，双方根据协商的算法产生共享的对称会话秘钥</li>
<li><strong>安全数据传输</strong>：双方用会话秘钥加密和解密它们之间传输的数据并验证其完整性</li>
</ol>
<p>https 绝对安全吗？</p>
<ul>
<li>中间人攻击：利用网络劫持和伪造证书，让浏览器认为中间人服务器就是目标服务器，中间人利用网络劫持就会将流量转发到目标服务器中，此时用户数据就会完全暴露。好在证书校验依赖 CA，一般都是比较权威的组织机构，故浏览器可以轻松识别出简单的证书异常（但仍存在继续浏览这样的风险存在）。验证一个数字证书是否合法，一般都是层层递归到最顶层的根证书，一般最顶层CA认证中心总是受信任的（全世界为数不多）。故自己导入根CA证书是不太安全的（因为无法验证其是否合法）</li>
</ul>
<p>详情参考 <a href="https://huangrenhao.gitee.io/2020/09/06/https-certificate/">https 与 ca</a></p>
<h3 id="rpc-与-RESTful"><a href="#rpc-与-RESTful" class="headerlink" title="rpc 与 RESTful"></a>rpc 与 RESTful</h3><p>rpc：remote procedure call，远程过程调用，即一个节点请求另一个节点的服务，与本地过程调用的区别在于服务存在于云端，故首先C需要告诉S调用的函数（函数与进程ID存在映射关系），C将本地参数传给远程函数（转化为字节流），S将结果序列化传给C，在TCP层完成。</p>
<blockquote>
<p>rpc 与本地过程调用相比：</p>
<ul>
<li>网络与一台计算机的情况更复杂，如可能限制消息大小，并且有丢失和重排消息的可能</li>
<li>双方可能有明显不同的体系结构和数据表示格式</li>
</ul>
</blockquote>
<p>为什么用 rpc：就是无法在一个进程内，甚至一个计算机内通过本地调用的方式完成的需求，比如不同的系统间的通讯，甚至不同的组织间的通讯，由于计算能力需要横向扩展，需要在多台机器组成的集群上部署应用。与 http 网络请求相比，没有 http 在应用层的消耗，效率更高。</p>
<blockquote>
<p>rpc 处于哪一层？对于协议体系结构应该严格分层的角度来说，rpc 是在传输层协议（通常是 UDP）上实现的。但实际上<strong>在因特网体系结构上实现 rpc 的方法与 rpc 是否是一个传输层协议无关</strong>。rpc 提供了一个与 tcp、udp 所提供该服务根本不同的进程到进程的服务，我们的观点是<strong>任何提供进程到进程的服务而不是节点到节点或主机到主机服务的协议都可以称作传输层协议</strong>，这样 <strong>rpc 就是一个传输层协议但可以在其他传输层协议之上来实现</strong>。</p>
</blockquote>
<p>rpc 需要执行的功能：</p>
<ul>
<li>提供一个名字空间来唯一标识被调用的过程</li>
<li>将每一个应答报文与请求报文匹配</li>
</ul>
<blockquote>
<p>名字空间：扁平 或 分层。扁平即唯一、无结构的标识符（如整数），分层即类似文件路径名。</p>
<p>将应答报文与请求报文匹配：使用报文id字段来识别请求-应答对。挑战是非预期的响应（与 id 有关，如客户机发送请求后重启有重新发送了相同的 id），这种解决方法是使用启动id（每次重启后都会自增）</p>
</blockquote>
<p>restful:</p>
<p>Representational State Transfer，表现层状态转化</p>
<p>Representation：表现层，“资源”具体呈现出来的形式，即格式，http 请求头信息中用 Accept、Content-Type 字段指定</p>
<p>State Transfer：“状态转化”，HTTP 请求中请求行的方法</p>
<ul>
<li><p>每一个URI代表一种资源；</p>
</li>
<li><p>客户端和服务器之间，传递这种资源的某种表现层；</p>
</li>
<li><p>客户端通过四个HTTP动词，对服务器端资源进行操作，实现”表现层状态转化”。Get 用来获取资源、post 用来新建资源（更新资源）、put 用来更新资源、delete 用来删除资源</p>
</li>
</ul>
<blockquote>
<p><a href="http://www.ruanyifeng.com/blog/2011/09/restful.html" target="_blank" rel="noopener">阮一峰 理解 RESTful 架构</a></p>
</blockquote>
<h3 id="http-协议的特点"><a href="#http-协议的特点" class="headerlink" title="http 协议的特点"></a>http 协议的特点</h3><ul>
<li>支持客户、服务器模式</li>
<li>简单快速：请求服务时，只需发送请求方法和路径，协议简单，通信速度快，能传输任意类型的数据对象，灵活（content-type 指出）</li>
<li>无连接：早期限制每次连接只处理一个请求，服务器处理完请求并受到客户应答后即断开连接，采用这种方式是早期每个客户端与服务器之间交换数据的间歇性较大，并且网页浏览的联想性、发散性导致两次传送的数据关联性很低，大部分通道实际上很空闲、无端占用资源。http 1.1 keep-alive 持久连接，避免重新建立连接</li>
<li>无状态：协议对事务处理没有记忆能力，服务器不知道客户端是什么状态。每个请求都是独立的，如果后续处理需要前面的信息则必须重传。缺点是每次请求会传输大量的重复信息，优点则是服务器可以根据需要将请求分发到集群中的任何一个节点，对缓存、负载均衡有好处。</li>
</ul>
<p><a href="https://www.cnblogs.com/xuxinstyle/p/9813654.html" target="_blank" rel="noopener">参考</a></p>
<h3 id="基于-udp、tcp-的协议有哪些"><a href="#基于-udp、tcp-的协议有哪些" class="headerlink" title="基于 udp、tcp 的协议有哪些"></a>基于 udp、tcp 的协议有哪些</h3><p>tcp</p>
<ul>
<li>http：保证顺序和信息完整</li>
<li>ftp：确保文件完整性</li>
<li>smtp、imap、pop3：邮件相关，需要保证信息完整</li>
<li>ssh、telnet：这两个协议用于访问远程主机，给用户提供一种和使用本地主机一样的体验</li>
</ul>
<p>udp</p>
<ul>
<li>dns</li>
<li>rstp：流媒体传输，实时性要求较高，不能花时间反复确认，视频掉帧也没有太大关系（如果用 tcp 则需要重传直到完整后才会传给应用层）</li>
<li>snmp：管理网络中各种基础硬件设施，比如路由器，交换机，防火墙等等。这些设备传输自己的参数</li>
<li>ntp：作用就是提供标准时间，可以用它来校准电脑时间</li>
<li>dhcp：动态分配IP，一开始不知道 dhcp 服务器的 ip，广播之后 dhcp 服务器响应报文</li>
</ul>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2020/09/24/js-interview/" rel="next" title="前端面试总结 js 部分">
                <i class="fa fa-chevron-left"></i> 前端面试总结 js 部分
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2020/09/24/http-next/" rel="prev" title="http2 和 http3">
                http2 和 http3 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
    </div>
  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">renhao</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">94</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">19</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#http-常见状态码"><span class="nav-number">1.</span> <span class="nav-text">http 常见状态码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#http-状态码中-301，302，307-的区别"><span class="nav-number">2.</span> <span class="nav-text">http 状态码中 301，302，307 的区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#http-状态码中-502-和-504-的区别"><span class="nav-number">3.</span> <span class="nav-text">http 状态码中 502 和 504 的区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#简述-http-的缓存机制"><span class="nav-number">4.</span> <span class="nav-text">简述 http 的缓存机制</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#强缓存"><span class="nav-number">4.1.</span> <span class="nav-text">强缓存</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#协商缓存"><span class="nav-number">4.2.</span> <span class="nav-text">协商缓存</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#http-proxy-的原理是什么"><span class="nav-number">5.</span> <span class="nav-text">http proxy 的原理是什么</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#随着-http2-的发展，前端性能优化中的哪些传统方案可以被替代"><span class="nav-number">6.</span> <span class="nav-text">随着 http2 的发展，前端性能优化中的哪些传统方案可以被替代</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#前端中的一些优化方法-前端性能优化"><span class="nav-number">7.</span> <span class="nav-text">前端中的一些优化方法/前端性能优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HTTP-1-0-、-HTTP-2-0、-HTTP-3-0"><span class="nav-number">8.</span> <span class="nav-text">HTTP 1.0 、 HTTP 2.0、 HTTP 3.0</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#websocket-、socket、-http"><span class="nav-number">9.</span> <span class="nav-text">websocket 、socket、 http</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#get-post-请求区别"><span class="nav-number">10.</span> <span class="nav-text">get post 请求区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#为什么-tcp-建立连接需要三次握手，而不是两次"><span class="nav-number">11.</span> <span class="nav-text">为什么 tcp 建立连接需要三次握手，而不是两次?</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-四次挥手为什么需要四次-能不能变成三次挥手"><span class="nav-number">12.</span> <span class="nav-text">tcp 四次挥手为什么需要四次? 能不能变成三次挥手?</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-四此挥手后为什么还需要等待-2msl"><span class="nav-number">13.</span> <span class="nav-text">tcp 四此挥手后为什么还需要等待 2msl</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#大量-TIME-WAIT-产生原因及解决方法"><span class="nav-number">14.</span> <span class="nav-text">大量 TIME_WAIT 产生原因及解决方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-在-listen-时参数-backlog-的意义"><span class="nav-number">15.</span> <span class="nav-text">tcp 在 listen 时参数 backlog 的意义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#accept-发生在三次握手的哪一步"><span class="nav-number">16.</span> <span class="nav-text">accept 发生在三次握手的哪一步</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#SYN-洪范攻击"><span class="nav-number">17.</span> <span class="nav-text">SYN 洪范攻击</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#DOS-攻击（拒绝服务攻击）"><span class="nav-number">18.</span> <span class="nav-text">DOS 攻击（拒绝服务攻击）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#死亡值-ping"><span class="nav-number">19.</span> <span class="nav-text">死亡值 ping</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-保活机制"><span class="nav-number">20.</span> <span class="nav-text">tcp 保活机制</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#出现-RST-包的原因"><span class="nav-number">21.</span> <span class="nav-text">出现 RST 包的原因</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-和-udp-区别"><span class="nav-number">22.</span> <span class="nav-text">tcp 和 udp 区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-为什么是可靠的"><span class="nav-number">23.</span> <span class="nav-text">tcp 为什么是可靠的</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-的滑动窗口和流量控制"><span class="nav-number">24.</span> <span class="nav-text">tcp 的滑动窗口和流量控制</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#滑动窗口"><span class="nav-number">24.1.</span> <span class="nav-text">滑动窗口</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#流量控制"><span class="nav-number">24.2.</span> <span class="nav-text">流量控制</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-的拥塞控制"><span class="nav-number">25.</span> <span class="nav-text">tcp 的拥塞控制</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tcp-粘包及拆包"><span class="nav-number">26.</span> <span class="nav-text">tcp 粘包及拆包</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#有哪些常见的服务端推送的通信解决方案？它们的优劣分别是什么？"><span class="nav-number">27.</span> <span class="nav-text">有哪些常见的服务端推送的通信解决方案？它们的优劣分别是什么？</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#content-type"><span class="nav-number">27.1.</span> <span class="nav-text">content-type</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cdn-原理"><span class="nav-number">28.</span> <span class="nav-text">cdn 原理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#https-amp-amp-ca"><span class="nav-number">29.</span> <span class="nav-text">https &amp;&amp; ca</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#rpc-与-RESTful"><span class="nav-number">30.</span> <span class="nav-text">rpc 与 RESTful</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#http-协议的特点"><span class="nav-number">31.</span> <span class="nav-text">http 协议的特点</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#基于-udp、tcp-的协议有哪些"><span class="nav-number">32.</span> <span class="nav-text">基于 udp、tcp 的协议有哪些</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">renhao</span>

  
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    
      <span class="post-meta-item-text">Site words total count&#58;</span>
    
    <span title="Site words total count">265.9k</span>
  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Muse</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  










  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src="//unpkg.com/valine/dist/Valine.min.js"></script>
  
  <script type="text/javascript">
    var GUEST = ['nick','mail','link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item=>{
      return GUEST.indexOf(item)>-1;
    });
    new Valine({
        el: '#comments' ,
        verify: false,
        notify: false,
        appId: '2P1xqUWiCoNm14MH4yhURlJi-gzGzoHsz',
        appKey: 'uJN0uagHIVgXtBO1OuLV9Ban',
        placeholder: 'Just go go',
        avatar:'mm',
        guest_info:guest,
        pageSize:'10' || 10,
    });
  </script>



  





  

  

  

  
  

  

  

  

</body>
</html>
